//IO多路复用技术poll函数的使用 
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <poll.h>
#include "wrap.h"
#include <sys/epoll.h>

int main()
{
	int k = 0;
	int ret ;
	int epfd;
	int i = 0;
	int n;
	int sockfd;
	int lfd;
	int cfd;
	int nready;
	char buf[1024];

	struct epoll_event events[1024];

	struct sockaddr_in svraddr;

	//创建socket
	lfd = Socket(AF_INET, SOCK_STREAM, 0);

	//允许端口复用
	int opt = 1;
	setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));

	//绑定bind
	svraddr.sin_family = AF_INET;
	svraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	svraddr.sin_port = htons(6666);
	ret = Bind(lfd, (struct sockaddr *)&svraddr, sizeof(struct sockaddr_in));

	//监听listen
	ret = Listen(lfd, 128);

	//创建一棵epoll树
	epfd = epoll_create(1);
	if(epfd < 0)
	{
		perror("create epoll error");
		return -1;
	}

	struct epoll_event ev;
	//将lfd上epoll树
	ev.data.fd = lfd;
	//表示读事件
	ev.events = EPOLLIN;

	epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);

	while(1)
	{
		nready = epoll_wait(epfd,events,1024,-1);
		if(nready<0)
		{
			perror("epoll_wait error");
			if(errno==EINTR)
			{
				continue;
			}
			break;
		}

		for(i=0;i<nready;i++)
		{
			sockfd = events[i].data.fd;
			//有客户端链接请求
			if(sockfd == lfd)
			{
				cfd = Accept(lfd,NULL,NULL);
				//将新的cfd上树
				ev.data.fd = cfd;
				ev.events = EPOLLIN;
				epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);
				continue;
			}

			//有数据发过来
			memset(buf,0,sizeof(buf));
			n = Read(sockfd,buf,sizeof(buf));
			if(n<=0)
			{
				close(sockfd);
				//将sockfd对应的事件节点从epoll树上删除
				epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);
			}
			else
			{
				printf("buf==[%s]\n",buf);
				for(k=0;k<n;k++)
				{
					buf[k] = toupper(buf[k]);
				}
				write(sockfd,buf,n);
			}
		}
	}
	close(lfd);
	return 0;
}
